#ifndef _CPP_STORY_STEP_DEFINITION_H_
#define _CPP_STORY_STEP_DEFINITION_H_

#include <pcre.h>
#include <string>
#include <vector>
#include <map>
#ifdef WIN32
#include "cppstory_win32.h"
#endif

#define OVECCOUNT 30

namespace CppStory
{

class ContextPtr;
class Table;
class Step;

typedef struct
{
    int count;
    int ovector[OVECCOUNT];
    int cur_group_index;
    std::string match_str;
} MatchInfo;

#ifdef WIN32
class CPPSTORY_WIN32_API StepDefinition
#else
class StepDefinition
#endif
{
public:
    StepDefinition(std::string str, const char* f, const int l);
    virtual ~StepDefinition();
    const char* get_regex_str() { return regex_str.c_str(); }
    bool match(Step* s, const char* match_str);
    bool run(Step* s);
    const int group_count();
    const std::string& get_next_group();
    virtual bool run_impl() { return false; }

    void register_context_ptr(ContextPtr *c);
    std::vector< ContextPtr* > context_ptrs;
    void clean_context_ptrs();

    Table* get_table();

    const char* get_file() { return file.c_str(); }
    const int get_line() { return line; }
    bool get_result(Step* s);

    void set_failed_file(const char* f) { failed_file = f; }
    void set_failed_line(const int l) { failed_line = l; }
    void set_failed_message(const char* m) { failed_message = m; }
    const char* get_failed_file() { return failed_file.c_str(); }
    const int get_failed_line() { return failed_line; }
    const char* get_failed_message() { return failed_message.c_str(); }
private:
    void erase_quoting(std::string s);
    std::string regex_str;
    std::string group_str;
    pcre* pcre_handle;
    std::map <Step*, MatchInfo> matched_steps;
    std::map <Step*, bool> step_results;
    std::string file;
    int line;
    bool result;
    std::string failed_file;
    int failed_line;
    std::string failed_message;
    Step* cur_matched_step;
};

}

#endif

